﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;

namespace CompileScript
{
    public class CCompileScript : MarshalByRefObject 
    {
        public string[] GenerateAssemblyFrom(string pathSource, string pathTarget, string pathTemp, bool bDebugInfo, string[] refAssemblies , ref bool bSuccess )
        {
            ArrayList outputMsg  = new ArrayList();
            bSuccess = false;

            try
            {
                CSharpCodeProvider codeProvider = new CSharpCodeProvider();
                CompilerParameters compilerParams = new CompilerParameters();
                compilerParams.CompilerOptions = "/target:library /optimize";
                compilerParams.GenerateInMemory = false;
                compilerParams.GenerateExecutable = false;

                compilerParams.IncludeDebugInformation = bDebugInfo;
                compilerParams.OutputAssembly = pathTarget;
                
                compilerParams.TempFiles = new TempFileCollection(pathTemp, false);
                foreach(string str in refAssemblies)
                    compilerParams.ReferencedAssemblies.Add(str);

                CompilerResults CompileResult = codeProvider.CompileAssemblyFromFile(compilerParams, pathSource);

                if (CompileResult.Errors.Count > 0)
                {
                    for (int i = 0; i < CompileResult.Output.Count; i++)
                    {
                        outputMsg.Add(CompileResult.Output[i].ToString());
                    }

                    for (int i = 0; i < CompileResult.Errors.Count; i++)
                    {
                        outputMsg.Add(CompileResult.Errors[i].ToString());
                    }
                }
                else
                {
                    bSuccess = true;

                    // Display information about the compiler's exit code and the generated assembly.
                    outputMsg.Add(string.Format("Compiler returned with result code: " + CompileResult.NativeCompilerReturnValue.ToString() ));
                    outputMsg.Add(string.Format("Generated assembly name: " + CompileResult.CompiledAssembly.FullName));
                    if (CompileResult.PathToAssembly == null)
                        outputMsg.Add(string.Format("The assembly has been generated in memory."));
                    else
                        outputMsg.Add(string.Format("Path to assembly: " + CompileResult.PathToAssembly));

                    // Display temporary files information.
                    if (!CompileResult.TempFiles.KeepFiles)
                        outputMsg.Add(string.Format("Temporary build files were deleted."));
                    else
                    {
                        outputMsg.Add(string.Format("Temporary build files were not deleted."));
                        // Display a list of the temporary build files
                        IEnumerator enu = CompileResult.TempFiles.GetEnumerator();
                        for (int i = 0; enu.MoveNext(); i++)
                            outputMsg.Add(string.Format("TempFile " + i.ToString() + ": " + (string)enu.Current));
                    }
                }
            }
            catch (System.Exception ex)
            {
                outputMsg.Add(ex.ToString());
            }

            string[] outputMsgRet = new string[outputMsg.Count];
            for (int i = 0; i < outputMsg.Count; i++)
                outputMsgRet[i] = (string) outputMsg[i];

            return outputMsgRet;
        }
    }
}
